import DOMPurify from 'dompurify';
import { defaultXssConfig, xssBlacklist, dangerousTags, getXssConfig } from '../config/xss-config';

/**
 * XSS防护工具类
 * 用于清理和转义用户输入，防止XSS攻击
 */

/**
 * 清理HTML内容，移除潜在的XSS攻击代码
 * @param htmlContent - 原始HTML内容
 * @param config - XSS配置（可选）
 * @returns 清理后的安全HTML内容
 */
export function sanitizeHtml(htmlContent: string, config = defaultXssConfig): string {
  if (!htmlContent || typeof htmlContent !== 'string') {
    return htmlContent;
  }
  
  // 检查内容长度
  if (htmlContent.length > config.maxLength) {
    htmlContent = htmlContent.substring(0, config.maxLength);
  }
  
  // 使用DOMPurify清理内容
  const cleanedContent = DOMPurify.sanitize(htmlContent, {
    ALLOWED_TAGS: config.allowedTags,
    ALLOWED_ATTR: config.allowedAttributes,
    ALLOW_DATA_ATTR: config.allowDataAttributes,
    ALLOWED_URI_REGEXP: config.strictUrlValidation 
      ? /^(?:(?:https?|mailto):|\/[^\/\0])/i 
      : undefined,
  });
  
  // 应用自定义规则
  let finalContent = cleanedContent;
  if (config.customRules) {
    for (const rule of config.customRules) {
      finalContent = finalContent.replace(rule.pattern, rule.replacement);
    }
  }
  
  return finalContent;
}

/**
 * 清理纯文本内容，转义HTML特殊字符
 * @param textContent - 原始文本内容
 * @returns 转义后的安全文本内容
 */
export function sanitizeText(textContent: string): string {
  if (!textContent || typeof textContent !== 'string') {
    return textContent;
  }
  // 对纯文本进行HTML转义
  return textContent
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
    .replace(/\//g, '&#x2F;');
}

/**
 * 清理富文本编辑器内容
 * @param richContent - 富文本内容
 * @param config - XSS配置（可选，默认为富文本配置）
 * @returns 清理后的安全富文本内容
 */
export function sanitizeRichContent(richContent: string, config = getXssConfig('rich')): string {
  return sanitizeHtml(richContent, config);
}

/**
 * 清理URL参数
 * @param url - URL字符串
 * @returns 清理后的安全URL
 */
export function sanitizeUrl(url: string): string {
  if (!url || typeof url !== 'string') {
    return url;
  }
  // 只允许http, https, mailto协议
  const allowedProtocols = ['http:', 'https:', 'mailto:'];
  try {
    const urlObj = new URL(url);
    if (allowedProtocols.includes(urlObj.protocol)) {
      return url;
    }
    return '#';
  } catch {
    return '#';
  }
}

/**
 * 清理用户输入（通用方法）
 * @param input - 用户输入
 * @param inputType - 输入类型 ('text' | 'html' | 'rich' | 'comment')
 * @param config - 自定义配置（可选）
 * @returns 清理后的安全输入
 */
export function sanitizeInput(
  input: string, 
  inputType: 'text' | 'html' | 'rich' | 'comment' = 'text',
  config?: any
): string {
  switch (inputType) {
    case 'html':
      return sanitizeHtml(input, config);
    case 'rich':
      return sanitizeRichContent(input, config);
    case 'comment':
      return sanitizeHtml(input, getXssConfig('comment'));
    case 'text':
    default:
      return sanitizeText(input);
  }
}

/**
 * 验证输入是否包含潜在的XSS攻击代码
 * @param input - 待验证的输入
 * @returns 是否包含潜在的XSS代码
 */
export function containsPotentialXss(input: string): boolean {
  if (!input || typeof input !== 'string') {
    return false;
  }
  
  // 检查危险标签
  const dangerousTagPattern = new RegExp(`&lt;(${dangerousTags.join('|')})[^&gt;]*&gt;`, 'gi');
  if (dangerousTagPattern.test(input)) {
    return true;
  }
  
  // 检查事件处理器
  const eventPattern = new RegExp(`(${xssBlacklist.join('|')})\\s*=`, 'gi');
  if (eventPattern.test(input)) {
    return true;
  }
  
  // 检查危险的URL协议
  const protocolPattern = /(javascript:|vbscript:|livescript:|mocha:|data:text\/html)/gi;
  if (protocolPattern.test(input)) {
    return true;
  }
  
  // 检查CSS表达式
  const cssExpressionPattern = /expression\s*\(|behavior\s*:|binding\s*:/gi;
  if (cssExpressionPattern.test(input)) {
    return true;
  }
  
  // 检查未编码的HTML标签
  const htmlTagPattern = /<[^>]+>/g;
  if (htmlTagPattern.test(input)) {
    return true;
  }
  
  return false;
}

export default {
  sanitizeHtml,
  sanitizeText,
  sanitizeRichContent,
  sanitizeUrl,
  sanitizeInput,
  containsPotentialXss,
};